//
//  BLECommand.swift
//  WNLockDemo
//
//  Created by 裴威 on 30/08/2018.
//  Copyright © 2018 wunu. All rights reserved.
//

import Foundation

/// 悟牛智能锁相关指令
///
/// - check: 查询智能锁状态
/// - bind: 绑定锁
/// - unbind: 解绑锁
/// - openstep1: 开锁第一步
/// - openstep2: 开锁第二步
enum WNLockCommamd {
    case check
    case bind(baseCode: UInt32, openId: UInt32)
    case unbind(baseCode: UInt32, openId: UInt32)
    case openstep1(xxetaV: [UInt32])
    case openstep2(xxetaV: [UInt32])
}

class BLECommandBuilder: NSObject {
    private var command: WNLockCommamd
    init(command: WNLockCommamd) {
        self.command = command
        super.init()
    }
    
    /// 获取指令流
    ///
    /// - Returns: Data
    func getCommandData() -> Data {
        switch command {
        case .check:
            let output = DataOutputStream()
            output.write(uint16: 0xaaaa)
            output.write(uint8: 0xc0)
            output.write(uint8: 0x00)
            output.write(uint8: checkSum(output.data))
            return output.data
        case let .bind(baseCode, openId):
            let output = DataOutputStream()
            output.write(uint16: 0xaaaa)
            output.write(uint16: 0xc208)
            output.write(uint32: baseCode)
            output.write(uint32: openId)
            output.write(uint8: checkSum(output.data))
            return output.data
        case let .unbind(baseCode, openId):
            let output = DataOutputStream()
            output.write(uint16: 0xaaaa)
            output.write(uint16: 0xc408)
            output.write(uint32: baseCode)
            output.write(uint32: openId)
            output.write(uint8: checkSum(output.data))
            return output.data
        case let .openstep1(xxetaV):
            let output = DataOutputStream()
            output.write(uint16: 0xaaaa)
            output.write(uint8: 0xb0)
            output.write(uint8: 0x04)
            output.write(uint32: xxetaV[0])
            output.write(uint32: xxetaV[1])
            output.write(uint8: checkSum(output.data))
            return output.data
        case let .openstep2(xxetaV):
            let output = DataOutputStream()
            output.write(uint16: 0xaaaa)
            output.write(uint8: 0xb2)
            output.write(uint8: 0x04)
            output.write(uint32: xxetaV[0])
            output.write(uint32: xxetaV[1])
            output.write(uint8: checkSum(output.data))
            return output.data
        }
    }
    
    func getResponseInfo(data: Data) -> [String: Any] {
        let input = DataInputStream(data: data)
        let head = input.readBytes(len: 2)
        if (UInt(head[0]) << 8) + UInt(head[1]) != 0xaaaa {
            return [:]
        }
        let _ = input.readBytes(len: 1) // 标识
        let _ = input.readBytes(len: 1) // 数据长度
//        let _ = input.readBytes(len: UInt(len[0]))
        switch command {
        case .check:
            let macBytes = input.readBytes(len: 6)// mac 地址
            let mac = macBytes.reversed().map { String(format: "%02X", $0) }.joined(separator: ":")
            let status = input.readBytes(len: 1)//状态
            return ["macAddr": mac, "status": status[0]]
        case .bind:
            let code = input.readBytes(len: 1)[0]
            return ["code": code]
        case .unbind:
            let code = input.readBytes(len: 1)[0]
            return ["code": code]
        case .openstep1:
            let n = input.readBytes(len: 1)[0]
            return ["n": n]
        case .openstep2:
            let code = input.readBytes(len: 1)[0]
            return ["code": code]
        }
    }
}

extension BLECommandBuilder {
    fileprivate var checkSum: (Data) -> UInt8 {
        let ckm = {data in
            let bytes = [UInt8](data)
            let sum = bytes.map{UInt($0)}.reduce(0, +)
            return UInt8(sum & 0xff)
            } as (Data) -> UInt8
        return ckm
    }
}
